/*
编写者：王出日
日期：2025，1，20
版本 0.5.0
描述：工具类，用于管理大模型的工具
包含：
Tools类：用于管理大模型的工具，包括注册、查询、调用等功能
*/

import 'dart:async';

/// 工具未找到异常
class ToolNotFound implements Exception {
  final String toolName;
  ToolNotFound(this.toolName);
  
  @override
  String toString() => 'Tool not found: $toolName';
}

/// 工具添加错误异常
class ToolsAddError implements Exception {
  @override
  String toString() => 'Tools can only be added with another Tools instance';
}

/// 后处理器类型错误异常
class PostHandlerTypeError implements Exception {
  final String toolName;
  final String expectedType;
  final String actualType;
  final String message;
  
  PostHandlerTypeError(this.toolName, this.expectedType, this.actualType, this.message);
  
  @override
  String toString() => 'PostHandlerTypeError for tool $toolName: $message';
}

/// 工具信息类
class ToolInfo {
  final String name;
  final List<String> parameters;
  
  ToolInfo({required this.name, required this.parameters});
}

/// 使用此类来管理你的工具，可以注册、查询、调用等功能
class Tools {
  final List<Map<String, dynamic>> _tools = [];
  final Map<String, Function> _toolFunctions = {};
  final List<String> _toolNameList = [];
  final List<ToolInfo> _toolParametersList = [];
  final Map<String, Function?> _postHandlers = {};

  /// 构造函数
  Tools();

  /// 重载 + 操作符，合并两个Tools实例
  Tools operator +(Tools other) {
    final combined = Tools();
    
    // 复制当前实例的内容
    combined._tools.addAll(_tools);
    combined._toolFunctions.addAll(_toolFunctions);
    combined._toolNameList.addAll(_toolNameList);
    combined._toolParametersList.addAll(_toolParametersList);
    combined._postHandlers.addAll(_postHandlers);
    
    // 添加另一个实例的工具（避免重复）
    for (int i = 0; i < other._tools.length; i++) {
      final toolName = other._tools[i]['function']['name'] as String;
      if (!combined._toolNameList.contains(toolName)) {
        combined._tools.add(other._tools[i]);
        combined._toolNameList.add(toolName);
        if (i < other._toolParametersList.length) {
          combined._toolParametersList.add(other._toolParametersList[i]);
        }
        final otherTool = other._toolFunctions[toolName];
        if (otherTool != null) {
          combined._toolFunctions[toolName] = otherTool;
        }
        combined._postHandlers[toolName] = other._postHandlers[toolName];
      }
    }
    
    return combined;
  }

  /// 注册没有函数实现的工具（仅注册schema）
  void registerNotWithFunction({
    required String name,
    required String description,
    required List<String> requiredParameters,
    required Map<String, Map<String, String>> parameters,
  }) {
    if (name.isEmpty) {
      throw ArgumentError('函数名称必须是非空字符串');
    }
    
    _toolNameList.add(name);
    _toolParametersList.add(ToolInfo(
      name: name,
      parameters: parameters.entries
          .map((e) => '${e.key}:${e.value['type']}')
          .toList(),
    ));
    
    final Map<String, dynamic> properties = {};
    parameters.forEach((key, value) {
      properties[key] = {
        'type': value['type']?.toLowerCase() == 'string' ? 'string' : value['type'],
        'description': value['description'] ?? '',
      };
    });
    
    _tools.add({
      'type': 'function',
      'function': {
        'name': name,
        'description': description,
        'parameters': {
          'type': 'object',
          'required': requiredParameters,
          'properties': properties,
        },
      },
    });
  }

  /// 注册工具装饰器
  Function registerDecorator({String? description, Function? postHandler}) {
    return (Function tool) {
      registerTool(
        tool: tool,
        description: description,
        postHandler: postHandler,
      );
      return tool;
    };
  }

  /// 注册工具
  Map<String, dynamic> registerTool({
    required Function tool,
    String? name,
    String? description,
    Function? postHandler,
    List<String>? requiredParameters,
    Map<String, Map<String, String>>? parameters,
  }) {
    final toolName = name ?? _getFunctionName(tool);
    
    if (_toolNameList.contains(toolName)) {
      return _tools.last; // 如果已存在，返回最后一个工具
    }
    
    _toolFunctions[toolName] = tool;
    _toolNameList.add(toolName);
    _postHandlers[toolName] = postHandler;
    
    // 解析函数参数
    final toolParameters = _parseToolParameters(
      tool, 
      description,
      requiredParameters: requiredParameters,
      parameters: parameters,
    );
    
    _toolParametersList.add(ToolInfo(
      name: toolName,
      parameters: toolParameters['properties']?.keys.toList().cast<String>() ?? [],
    ));
    
    final toolSchema = {
      'type': 'function',
      'function': {
        'name': toolName,
        'description': description ?? '无描述',
        'parameters': toolParameters,
      },
    };
    
    _tools.add(toolSchema);
    return toolSchema;
  }

  /// 解析工具参数
  Map<String, dynamic> _parseToolParameters(
    Function tool, 
    String? description, {
    List<String>? requiredParameters,
    Map<String, Map<String, String>>? parameters,
  }) {
    final Map<String, dynamic> properties = {};
    
    // 如果提供了参数定义，使用它们
    if (parameters != null) {
      parameters.forEach((paramName, paramDef) {
        properties[paramName] = {
          'type': paramDef['type'] ?? 'string',
          'description': paramDef['description'] ?? '无描述',
        };
        
        // 如果有默认值，添加它
        if (paramDef.containsKey('default')) {
          properties[paramName]['default'] = paramDef['default'];
        }
        
        // 如果有枚举值，添加它们
        if (paramDef.containsKey('enum')) {
          try {
            properties[paramName]['enum'] = paramDef['enum']!.split(',').map((e) => e.trim()).toList();
          } catch (e) {
            // 如果解析失败，忽略enum
          }
        }
      });
    }
    
    return {
      'type': 'object',
      'required': requiredParameters ?? [],
      'properties': properties,
    };
  }

  /// 获取函数名（简化版）
  String _getFunctionName(Function tool) {
    return 'anonymous_${tool.hashCode}';
  }

  /// 注销工具
  bool unregister(String name) {
    if (!_toolNameList.contains(name)) {
      throw ToolNotFound(name);
    }
    
    final index = _toolNameList.indexOf(name);
    _tools.removeAt(index);
    _toolNameList.removeAt(index);
    _toolParametersList.removeAt(index);
    _toolFunctions.remove(name);
    _postHandlers.remove(name);
    
    return true;
  }

  /// 禁用工具
  bool disableTool(String toolName) {
    // 简化实现，实际应该有enable/disable状态管理
    return _toolNameList.contains(toolName);
  }

  /// 启用工具
  bool enableTool(String toolName) {
    // 简化实现，实际应该有enable/disable状态管理
    return _toolNameList.contains(toolName);
  }

  /// 执行工具
  Future<String> execute(String name, {
    int timeout = 60,
    Map<String, dynamic>? kwargs,
  }) async {
    if (!_toolNameList.contains(name)) {
      return '❌ 工具执行失败: 工具 \'$name\' 不存在。请检查工具名称是否正确或是否已注册。';
    }
    
    final tool = _toolFunctions[name];
    if (tool == null) {
      return '❌ 工具执行失败: 工具 \'$name\' 无法获取。可能是内部错误，请联系开发者。';
    }
    
    try {
      // 执行工具
      dynamic result;
      if (kwargs != null && kwargs.isNotEmpty) {
        result = await _executeWithTimeout(tool, timeout, kwargs);
      } else {
        result = await _executeWithTimeout(tool, timeout, {});
      }
      
      // 应用后处理器
      final postHandler = _postHandlers[name];
      if (postHandler != null) {
        try {
          result = postHandler(result);
        } catch (e) {
          return '❌ 工具 \'$name\' 的后处理器执行失败: $e\n'
                 '💡 请检查后处理器的参数类型是否与工具输出类型匹配\n'
                 '工具原始输出: $result';
        }
      }
      
      return result.toString();
      
    } catch (e) {
      return '❌ 工具执行失败: $e';
    }
  }

  /// 带超时的工具执行
  Future<dynamic> _executeWithTimeout(
    Function tool,
    int timeout,
    Map<String, dynamic> kwargs,
  ) async {
    return Future.any([
      _callTool(tool, kwargs),
      Future.delayed(Duration(seconds: timeout)).then((_) {
        throw TimeoutException('工具执行超时', Duration(seconds: timeout));
      }),
    ]);
  }

  /// 调用工具
  Future<dynamic> _callTool(Function tool, Map<String, dynamic> kwargs) async {
    try {
      // 根据参数数量调用工具函数
      if (kwargs.isEmpty) {
        return await tool();
      }
      
      // 按参数数量动态调用
      final values = kwargs.values.toList();
      switch (values.length) {
        case 1:
          return await tool(values[0]);
        case 2:
          return await tool(values[0], values[1]);
        case 3:
          return await tool(values[0], values[1], values[2]);
        case 4:
          return await tool(values[0], values[1], values[2], values[3]);
        case 5:
          return await tool(values[0], values[1], values[2], values[3], values[4]);
        default:
          // 对于更多参数的情况，使用Function.apply（有限制但可以处理大多数情况）
          return await Function.apply(tool, values);
      }
    } catch (e) {
      // 如果同步调用失败，尝试异步调用
      try {
        final result = tool is Function
            ? Function.apply(tool, kwargs.values.toList())
            : tool();
        return result is Future ? await result : result;
      } catch (e2) {
        rethrow; // 重新抛出原始异常
      }
    }
  }

  /// 检查工具是否存在
  bool checkTools(String name) {
    return _toolNameList.contains(name);
  }

  /// 获取工具列表
  List<Map<String, dynamic>> getTools({bool enable = true}) {
    return List.from(_tools);
  }

  /// 获取工具函数
  Function? getTool(String name) {
    return _toolFunctions[name];
  }

  /// 获取后处理器
  Function? getPostHandler(String name) {
    return _postHandlers[name];
  }

  /// 获取工具名称列表
  List<String> getToolNameList() {
    return List.from(_toolNameList);
  }

  /// 获取工具参数列表
  List<ToolInfo> getToolParametersList() {
    return List.from(_toolParametersList);
  }
}
